<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">

    <title>Progress — Space.js</title>

    <link rel="preconnect" href="https://fonts.gstatic.com">
    <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Roboto+Mono">
    <link rel="stylesheet" href="assets/css/style.css">

    <script type="module">
        import { Interface, clearTween, ticker, tween } from '../src/index.js';

        class Progress extends Interface {
            constructor() {
                super(null, 'svg');

                const size = 90;

                this.width = size;
                this.height = size;
                this.x = size / 2;
                this.y = size / 2;
                this.radius = size * 0.4;
                this.progress = 0;
                this.needsUpdate = false;

                this.initSVG();

                this.addListeners();
            }

            initSVG() {
                this.attr({
                    width: this.width,
                    height: this.height
                });

                this.circle = new Interface(null, 'svg', 'circle');
                this.circle.attr({
                    cx: this.x,
                    cy: this.y,
                    r: this.radius
                });
                this.circle.css({
                    fill: 'none',
                    stroke: 'var(--ui-color)',
                    strokeWidth: 1.5
                });
                this.circle.start = 0;
                this.circle.offset = -0.25;
                this.add(this.circle);
            }

            addListeners() {
                ticker.add(this.onUpdate);
            }

            removeListeners() {
                ticker.remove(this.onUpdate);
            }

            // Event handlers

            onUpdate = () => {
                if (this.needsUpdate) {
                    this.update();
                }
            };

            onProgress = ({ progress }) => {
                clearTween(this);

                this.needsUpdate = true;

                tween(this, { progress }, 500, 'easeOutCubic', () => {
                    this.needsUpdate = false;

                    if (this.progress >= 1) {
                        this.onComplete();
                    }
                });
            };

            onComplete = () => {
                this.removeListeners();

                this.events.emit('complete');
            };

            // Public methods

            update = () => {
                this.circle.line(this.progress);
            };

            animateOut = callback => {
                this.tween({ scale: 0.9, opacity: 0 }, 400, 'easeInCubic', callback);
            };

            destroy = () => {
                this.removeListeners();

                clearTween(this);

                return super.destroy();
            };
        }

        class App {
            static init() {
                this.initView();

                this.addListeners();
            }

            static initView() {
                this.view = new Progress();
                this.view.css({
                    position: 'absolute',
                    left: '50%',
                    top: '50%',
                    marginLeft: -this.view.width / 2,
                    marginTop: -this.view.height / 2,
                    cursor: 'pointer'
                });
                document.body.appendChild(this.view.element);

                this.view.onProgress({ progress: 1 });
            }

            static addListeners() {
                this.view.element.addEventListener('click', this.onClick);
                ticker.start();
            }

            // Event handlers

            static onClick = () => {
                this.view.element.removeEventListener('click', this.onClick);

                this.view.animateOut(() => {
                    this.view = this.view.destroy();
                });
            };
        }

        App.init();
    </script>
</head>
<body>
</body>
</html>
